package com.muyu.payment.controller;

import com.muyu.common.core.web.controller.BaseController;
import com.muyu.common.core.domain.Result;
import com.muyu.common.core.web.page.DataPageResp;
import com.muyu.payment.domain.BalanceTransaction;
import com.muyu.payment.domain.RechargeOrder;
import com.muyu.payment.domain.UserBalance;
import com.muyu.payment.domain.WithdrawOrder;
import com.muyu.payment.domain.req.RechargeReq;
import com.muyu.payment.domain.req.WithdrawReq;
import com.muyu.payment.domain.resp.BalanceResp;
import com.muyu.payment.domain.resp.RechargeResp;
import com.muyu.payment.domain.resp.WithdrawResp;
import com.muyu.payment.mapper.BalanceTransactionMapper;
import com.muyu.payment.mapper.RechargeOrderMapper;
import com.muyu.payment.mapper.WithdrawOrderMapper;
import com.muyu.payment.service.RechargeService;
import com.muyu.payment.service.UserBalanceService;
import com.muyu.payment.service.WithdrawService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;


import java.util.List;

/**
 * 余额管理控制器
 *
 * @author muyu
 * @date 2025-01-27
 */
@Slf4j
@RestController
@RequestMapping("/payment/balance")
@CrossOrigin(origins = "*", allowedHeaders = "*", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.OPTIONS})
@Tag(name = "余额管理", description = "用户余额充值和提现相关接口")
public class BalanceController extends BaseController {

    @Autowired
    private UserBalanceService userBalanceService;

    @Autowired
    private RechargeService rechargeService;

    @Autowired
    private WithdrawService withdrawService;

    @Autowired
    private BalanceTransactionMapper balanceTransactionMapper;

    @Autowired
    private RechargeOrderMapper rechargeOrderMapper;

    @Autowired
    private WithdrawOrderMapper withdrawOrderMapper;

    /**
     * 健康检查接口
     */
    @GetMapping("/health")
    @Operation(summary = "健康检查", description = "检查服务是否正常运行")
    public Result<String> health() {
        try {
            log.info("健康检查接口被调用");
            return Result.success("服务运行正常");
        } catch (Exception e) {
            log.error("健康检查失败", e);
            e.printStackTrace();
            return Result.error("健康检查失败: " + e.getMessage());
        }
    }

    


    /**
     * 查询用户余额
     */
    @GetMapping("/query")
    @Operation(summary = "查询用户余额", description = "根据用户ID查询当前余额信息")
    public Result<BalanceResp> queryBalance(@Parameter(description = "用户ID", required = true) @RequestParam("userId") Long userId) {
        try {
            log.info("开始查询用户余额，用户ID: {}", userId);
            
            UserBalance userBalance = userBalanceService.getBalanceByUserId(userId);
            if (userBalance == null) {
                log.info("用户余额不存在，开始初始化，用户ID: {}", userId);
                // 如果用户余额不存在，初始化余额
                userBalance = userBalanceService.initUserBalance(userId, "user_" + userId);
                log.info("用户余额初始化成功，用户ID: {}", userId);
            }
            
            // 转换为响应对象
            BalanceResp balanceResp = new BalanceResp();
            balanceResp.setUserId(userBalance.getUserId());
            balanceResp.setUserName(userBalance.getUserName());
            balanceResp.setBalance(userBalance.getBalance());
            balanceResp.setStatus(userBalance.getStatus());
            
            log.info("查询用户余额成功，用户ID: {}, 余额: {}", userId, userBalance.getBalance());
            return success(balanceResp);
        } catch (Exception e) {
            log.error("查询用户余额失败，用户ID: {}", userId, e);
            e.printStackTrace(); // 打印详细错误堆栈
            return Result.error("查询用户余额失败: " + e.getMessage());
        }
    }

    /**
     * 用户充值
     */
    @PostMapping("/recharge")
    @Operation(summary = "用户充值", description = "创建充值订单并返回支付信息")
    public Result<RechargeResp> recharge(@Parameter(description = "用户ID", required = true) @RequestParam("userId") Long userId,
                              @Parameter(description = "充值请求", required = true) @RequestBody @Validated RechargeReq request,
                              HttpServletRequest httpRequest) {
        try {
            log.info("收到充值请求，用户ID: {}, 金额: {}, 支付渠道: {}", userId, request.getAmount(), request.getPayChannel());
            
            // 获取客户端IP
            String clientIp = getClientIp(httpRequest);
            request.setClientIp(clientIp);

            // 创建充值订单并调用第三方支付接口
            RechargeResp rechargeResp = rechargeService.createRechargeOrderWithPayment(userId, "user_" + userId, request);
            
            log.info("充值订单创建成功，订单号: {}", rechargeResp.getOrderNo());
            
            return Result.success(rechargeResp, "充值订单创建成功，请完成支付");
        } catch (Exception e) {
            log.error("创建充值订单失败，用户ID: {}, 金额: {}", userId, request.getAmount(), e);
            e.printStackTrace(); // 打印详细错误堆栈
            return Result.error("创建充值订单失败: " + e.getMessage());
        }
    }

    /**
     * 用户提现
     */
    @PostMapping("/withdraw")
    @Operation(summary = "用户提现", description = "创建提现申请")
    public Result<WithdrawResp> withdraw(@Parameter(description = "提现请求", required = true) @RequestBody @Validated WithdrawReq request,
                              @Parameter(description = "用户ID", required = true) @RequestParam("userId") Long userId) {
        try {
            // 创建提现订单
            WithdrawOrder withdrawOrder = withdrawService.createWithdrawOrder(userId, "user_" + userId, request);
            
            // 转换为响应对象
            WithdrawResp withdrawResp = new WithdrawResp();
            withdrawResp.setOrderNo(withdrawOrder.getOrderNo());
            withdrawResp.setUserId(withdrawOrder.getUserId());
            withdrawResp.setAmount(withdrawOrder.getAmount());
            withdrawResp.setFee(withdrawOrder.getFee());
            withdrawResp.setActualAmount(withdrawOrder.getActualAmount());
            withdrawResp.setPayType(withdrawOrder.getPayType());
            withdrawResp.setReceiveAccount(withdrawOrder.getReceiveAccount());
            withdrawResp.setReceiveName(withdrawOrder.getReceiveName());
            withdrawResp.setOrderStatus(withdrawOrder.getOrderStatus());
            withdrawResp.setCreateTime(withdrawOrder.getCreateTime());
            withdrawResp.setRemark(withdrawOrder.getRemark());
            
            return Result.success(withdrawResp, "提现申请提交成功，等待审核");
        } catch (Exception e) {
            log.error("创建提现订单失败，用户ID: {}, 金额: {}", userId, request.getAmount(), e);
            return Result.error("创建提现订单失败: " + e.getMessage());
        }
    }

    /**
     * 查询余额变动记录
     */
    @GetMapping("/transactions")
    @Operation(summary = "查询余额变动记录", description = "查询用户余额变动历史记录")
    public Result<DataPageResp<BalanceTransaction>> getTransactions(@Parameter(description = "用户ID", required = true) @RequestParam("userId") Long userId,
                                        @Parameter(description = "限制条数") @RequestParam(value = "limit", defaultValue = "20", required = false) Integer limit) {
        try {
            log.info("开始查询余额变动记录，用户ID: {}, 限制条数: {}", userId, limit);
            
            // 参数验证
            if (userId == null) {
                log.error("用户ID不能为空");
                return Result.error("用户ID不能为空");
            }
            
            if (limit == null || limit <= 0) {
                limit = 20; // 设置默认值
            }
            
            log.info("准备调用balanceTransactionMapper.selectByUserId，参数: userId={}, limit={}", userId, limit);
            
            List<BalanceTransaction> transactions = balanceTransactionMapper.selectByUserId(userId, limit);
            
            log.info("查询结果: transactions={}", transactions);
            
            // 确保transactions不为null
            if (transactions == null) {
                log.warn("查询结果为null，设置为空列表");
                transactions = new java.util.ArrayList<>();
            }
            
            // 使用Builder模式创建DataPageResp
            DataPageResp<BalanceTransaction> dataPageResp = DataPageResp.<BalanceTransaction>builder()
                    .rows(transactions)
                    .total(transactions.size())
                    .build();
            
            log.info("查询余额变动记录成功，用户ID: {}, 记录数: {}", userId, transactions.size());
            return success(dataPageResp);
        } catch (Exception e) {
            log.error("查询余额变动记录失败，用户ID: {}, 错误详情: {}", userId, e.getMessage(), e);
            e.printStackTrace(); // 打印详细错误堆栈
            
            // 返回空数据而不是错误，避免前端报错
            DataPageResp<BalanceTransaction> emptyResp = DataPageResp.<BalanceTransaction>builder()
                    .rows(new java.util.ArrayList<>())
                    .total(0L)
                    .build();
            return success(emptyResp);
        }
    }

    /**
     * 查询充值订单列表
     */
    @GetMapping("/recharge/orders")
    @Operation(summary = "查询充值订单列表", description = "查询用户充值订单历史")
    public Result<DataPageResp<RechargeOrder>> getRechargeOrders(@Parameter(description = "用户ID", required = true) @RequestParam("userId") Long userId,
                                        @Parameter(description = "限制条数") @RequestParam(value = "limit", defaultValue = "20") Integer limit) {
        try {
            List<RechargeOrder> orders = rechargeOrderMapper.selectByUserId(userId, limit);
            DataPageResp<RechargeOrder> dataPageResp = new DataPageResp<>();
            dataPageResp.setRows(orders);
            dataPageResp.setTotal(orders.size());
            return success(dataPageResp);
        } catch (Exception e) {
            log.error("查询充值订单列表失败，用户ID: {}", userId, e);
            return Result.error("查询充值订单列表失败");
        }
    }

    /**
     * 查询提现订单列表
     */
    @GetMapping("/withdraw/orders")
    @Operation(summary = "查询提现订单列表", description = "查询用户提现订单历史")
    public Result<DataPageResp<WithdrawOrder>> getWithdrawOrders(@Parameter(description = "用户ID", required = true) @RequestParam("userId") Long userId,
                                        @Parameter(description = "限制条数") @RequestParam(value = "limit", defaultValue = "20") Integer limit) {
        try {
            List<WithdrawOrder> orders = withdrawOrderMapper.selectByUserId(userId, limit);
            DataPageResp<WithdrawOrder> dataPageResp = new DataPageResp<>();
            dataPageResp.setRows(orders);
            dataPageResp.setTotal(orders.size());
            return success(dataPageResp);
        } catch (Exception e) {
            log.error("查询提现订单列表失败，用户ID: {}", userId, e);
            return Result.error("查询提现订单列表失败");
        }
    }

    /**
     * 根据订单号查询充值订单详情
     */
    @GetMapping("/recharge/order/{orderNo}")
    @Operation(summary = "查询充值订单详情", description = "根据订单号查询充值订单详细信息")
    public Result<RechargeOrder> getRechargeOrderByOrderNo(@Parameter(description = "订单号", required = true) @PathVariable("orderNo") String orderNo) {
        try {
            log.info("查询充值订单详情，订单号: {}", orderNo);
            
            RechargeOrder order = rechargeService.getRechargeOrderByOrderNo(orderNo);
            if (order == null) {
                log.warn("充值订单不存在，订单号: {}", orderNo);
                return Result.error("订单不存在");
            }
            
            log.info("查询充值订单详情成功，订单号: {}, 状态: {}", orderNo, order.getOrderStatus());
            return Result.success(order);
        } catch (Exception e) {
            log.error("查询充值订单详情失败，订单号: {}", orderNo, e);
            return Result.error("查询订单详情失败: " + e.getMessage());
        }
    }

    /**
     * 充值回调处理
     */
    @PostMapping("/recharge/callback")
    @Operation(summary = "充值回调处理", description = "处理第三方支付回调")
    public Result<String> rechargeCallback(@Parameter(description = "订单号", required = true) @RequestParam("orderNo") String orderNo,
                                      @Parameter(description = "第三方交易号") @RequestParam(value = "thirdPartyTradeNo", required = false) String thirdPartyTradeNo,
                                      @Parameter(description = "支付状态", required = true) @RequestParam("status") Integer status) {
        try {
            boolean success = rechargeService.handleRechargeCallback(orderNo, thirdPartyTradeNo, status);
            if (success) {
                return success("充值回调处理成功");
            } else {
                return error("充值回调处理失败");
            }
        } catch (Exception e) {
            log.error("处理充值回调失败，订单号: {}", orderNo, e);
            return error("处理充值回调失败: " + e.getMessage());
        }
    }

    /**
     * 取消充值订单
     */
    @PostMapping("/recharge/cancel")
    @Operation(summary = "取消充值订单", description = "取消待支付的充值订单")
    public Result<String> cancelRechargeOrder(@Parameter(description = "订单号", required = true) @RequestParam String orderNo) {
        try {
            boolean success = rechargeService.cancelRechargeOrder(orderNo);
            if (success) {
                return success("取消充值订单成功");
            } else {
                return error("取消充值订单失败");
            }
        } catch (Exception e) {
            log.error("取消充值订单失败，订单号: {}", orderNo, e);
            return error("取消充值订单失败: " + e.getMessage());
        }
    }

    /**
     * 取消提现订单
     */
    @PostMapping("/withdraw/cancel")
    @Operation(summary = "取消提现订单", description = "取消待审核的提现订单")
    public Result<String> cancelWithdrawOrder(@Parameter(description = "订单号", required = true) @RequestParam String orderNo) {
        try {
            boolean success = withdrawService.cancelWithdrawOrder(orderNo);
            if (success) {
                return success("取消提现订单成功");
            } else {
                return error("取消提现订单失败");
            }
        } catch (Exception e) {
            log.error("取消提现订单失败，订单号: {}", orderNo, e);
            return error("取消提现订单失败: " + e.getMessage());
        }
    }

    /**
     * 获取客户端IP地址
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}